﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SmartChess
{
    public class Game
    {
        public int[] Board;
        private int Pawn = 100;
        private int Knight = 320;
        private int Bishop = 330;
        private int Rook = 500;
        private int Queen = 900;
        private int King = 20000;
        private int counter = 0;
        private int[] WPawnTable, WKnightTable, WBishopTable, WRookTable, WQueenTable, WKingTable;
        private int[] BPawnTable, BKnightTable, BBishopTable, BRookTable, BQueenTable, BKingTable;

        private bool castlingRightforWhitePossible = true;//RochadeRecht rechter weißer Turm
        private bool castlingRightforBlackPossible = true;//RochadeRecht rechter schwarzer Turm
        private bool castlingLeftforWhitePossible = true;//RochadeRecht linker weißer Turm
        private bool castlingLeftforBlackPossible = true;//RochadeRecht linker schwazer turm           
        private bool _gameOver = false;     
        private GameRules gameRules = new GameRules();

        public enum UNIT
        {
            Free = 0,
            WPawn = 1,
            WKnight = 12,
            WBishop = 13,
            WRook = 11,
            WQueen = 14,
            WKing = 10,
            BPawn = 2,
            BKnight = 22,
            BBishop = 23,
            BRook = 21,
            BQueen = 24,
            BKing = 20
        }

        public Game()
        {
            BuildBoard();
            InitTables();
            
        }

        public Game(Game previousGame)
        {
            Board = new int[120];
            previousGame.Board.CopyTo(Board, 0);
            InitTables();
        }
        public int[] GetBoard()
        {
            return Board;
        }
        private void BuildBoard()
        {
            
            Board = new int[120] {
                -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
                -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
                -1, 21, 22, 23, 24, 20, 23, 22, 21, -1,
                -1,  2,  2,  2,  2,  2,  2,  2,  2, -1, 
                -1,  0,  0,  0,  0,  0,  0,  0,  0, -1,
                -1,  0,  0,  0,  0,  0,  0,  0,  0, -1,
                -1,  0,  0,  0,  0,  0,  0,  0,  0, -1,
                -1,  0,  0,  0,  0,  0,  0,  0,  0, -1,
                -1,  1,  1,  1,  1,  1,  1,  1,  1, -1,
                -1, 11, 12, 13, 14, 10, 13, 12, 11, -1,
                -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
                -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
            };
       
            /* Index: 
             * 0  1  2  3  4  5  6  7  8  9 
             * 10 11 12 13 14 15 16 17 18 19
             * 20 21 22 23 24 25 26 27 28 29
             * 30 31 32 33 34 35 36 37 38 39
             * 40 41 42 43 44 45 46 47 48 49
             * 50 51 52 53 54 55 56 57 58 59
             * 60 61 62 63 64 65 66 67 68 69
             * 70 71 72 73 74 75 76 77 78 79
             * 80 81 82 83 84 85 86 87 88 89
             * 90 91 92 93 94 95 96 97 98 99
             * 100 101 102 103 104 105 106 107 108 109
             * 110 111 112 113 114 115 116 117 118 119
             */


        }
        //Definiert die Punktzahl jeder Figur für jedes Feld
        private void InitTables()
        {
            WPawnTable = new int[64] {
                 0,  0,  0,  0,  0,  0,  0,  0,
                50, 50, 50, 50, 50, 50, 50, 50,
                10, 10, 20, 30, 30, 20, 10, 10,
                 5,  5, 10, 25, 25, 10,  5,  5,
                 0,  0,  0, 20, 20,  0,  0,  0,
                 5, -5,-10,  0,  0,-10, -5,  5,
                 5, 10, 10,-20,-20, 10, 10,  5,
                 0,  0,  0,  0,  0,  0,  0,  0
            };
            WKnightTable = new int[64] {
                -50,-40,-30,-30,-30,-30,-40,-50,
                -40,-20,  0,  0,  0,  0,-20,-40,
                -30,  0, 10, 15, 15, 10,  0,-30,
                -30,  5, 15, 20, 20, 15,  5,-30,
                -30,  0, 15, 20, 20, 15,  0,-30,
                -30,  5, 10, 15, 15, 10,  5,-30,
                -40,-20,  0,  5,  5,  0,-20,-40,
                -50,-40,-30,-30,-30,-30,-40,-50,
            };
            WBishopTable = new int[64] {
                -20,-10,-10,-10,-10,-10,-10,-20,
                -10,  0,  0,  0,  0,  0,  0,-10,
                -10,  0,  5, 10, 10,  5,  0,-10,
                -10,  5,  5, 10, 10,  5,  5,-10,
                -10,  0, 10, 10, 10, 10,  0,-10,
                -10, 10, 10, 10, 10, 10, 10,-10,
                -10,  5,  0,  0,  0,  0,  5,-10,
                -20,-10,-10,-10,-10,-10,-10,-20,
            };
            WRookTable = new int[64] {
                  0,  0,  0,  0,  0,  0,  0,  0,
                  5, 10, 10, 10, 10, 10, 10,  5,
                 -5,  0,  0,  0,  0,  0,  0, -5,
                 -5,  0,  0,  0,  0,  0,  0, -5,
                 -5,  0,  0,  0,  0,  0,  0, -5,
                 -5,  0,  0,  0,  0,  0,  0, -5,
                 -5,  0,  0,  0,  0,  0,  0, -5,
                  0,  0,  0,  5,  5,  0,  0,  0
            };
            WQueenTable = new int[64] {
                -20,-10,-10, -5, -5,-10,-10,-20,
                -10,  0,  0,  0,  0,  0,  0,-10,
                -10,  0,  5,  5,  5,  5,  0,-10,
                 -5,  0,  5,  5,  5,  5,  0, -5,
                  0,  0,  5,  5,  5,  5,  0, -5,
                -10,  5,  5,  5,  5,  5,  0,-10,
                -10,  0,  5,  0,  0,  0,  0,-10,
                -20,-10,-10, -5, -5,-10,-10,-20
            };
            WKingTable = new int[64] {
                -30,-40,-40,-50,-50,-40,-40,-30,
                -30,-40,-40,-50,-50,-40,-40,-30,
                -30,-40,-40,-50,-50,-40,-40,-30,
                -30,-40,-40,-50,-50,-40,-40,-30,
                -20,-30,-30,-40,-40,-30,-30,-20,
                -10,-20,-20,-20,-20,-20,-20,-10,
                 20, 20,  0,  0,  0,  0, 20, 20,
                 20, 30, 10,  0,  0, 10, 30, 20
            };



            BPawnTable = new int[64] {
                 0,  0,  0,  0,  0,  0,  0,  0,
                 5, 10, 10,-20,-20, 10, 10,  5, 
                 5, -5,-10,  0,  0,-10, -5,  5,
                 0,  0,  0, 20, 20,  0,  0,  0,
                 5,  5, 10, 25, 25, 10,  5,  5,
                10, 10, 20, 30, 30, 20, 10, 10,
                50, 50, 50, 50, 50, 50, 50, 50,
                 0,  0,  0,  0,  0,  0,  0,  0
            };
            BKnightTable = new int[64] {
                -50,-40,-30,-30,-30,-30,-40,-50,
                -40,-20,  0,  5,  5,  0,-20,-40,
                -30,  5, 10, 15, 15, 10,  5,-30,
                -30,  0, 15, 20, 20, 15,  0,-30,
                -30,  5, 15, 20, 20, 15,  5,-30,
                -30,  0, 10, 15, 15, 10,  0,-30,
                -40,-20,  0,  0,  0,  0,-20,-40,
                -50,-40,-30,-30,-30,-30,-40,-50
            };
            BBishopTable = new int[64] {
                -20,-10,-10,-10,-10,-10,-10,-20,
                -10,  5,  0,  0,  0,  0,  5,-10,
                -10, 10, 10, 10, 10, 10, 10,-10,
                -10,  0, 10, 10, 10, 10,  0,-10,
                -10,  5,  5, 10, 10,  5,  5,-10,
                -10,  0,  5, 10, 10,  5,  0,-10,
                -10,  0,  0,  0,  0,  0,  0,-10,
                -20,-10,-10,-10,-10,-10,-10,-20
            };
            BRookTable = new int[64] {
                  0,  0,  0,  5,  5,  0,  0,  0,
                 -5,  0,  0,  0,  0,  0,  0, -5,
                 -5,  0,  0,  0,  0,  0,  0, -5,
                 -5,  0,  0,  0,  0,  0,  0, -5,
                 -5,  0,  0,  0,  0,  0,  0, -5,
                 -5,  0,  0,  0,  0,  0,  0, -5,
                  5, 10, 10, 10, 10, 10, 10,  5,
                  0,  0,  0,  0,  0,  0,  0,  0
            };
            BQueenTable = new int[64] {
                -20,-10,-10, -5, -5,-10,-10,-20,
                -10,  0,  5,  0,  0,  0,  0,-10,
                -10,  5,  5,  5,  5,  5,  0,-10,
                 -0,  0,  5,  5,  5,  5,  0, -5,
                 -5,  0,  5,  5,  5,  5,  0, -5,
                -10,  0,  5,  5,  5,  5,  0,-10,
                -10,  0,  0,  0,  0,  0,  0,-10,
                -20,-10,-10, -5, -5,-10,-10,-20
            };
            BKingTable = new int[64] {
                 20, 30, 10,  0,  0, 10, 30, 20,
                 20, 20,  0,  0,  0,  0, 20, 20,
                -10,-20,-20,-20,-20,-20,-20,-10,
                -20,-30,-30,-40,-40,-30,-30,-20,
                -30,-40,-40,-50,-50,-40,-40,-30,
                -30,-40,-40,-50,-50,-40,-40,-30,
                -30,-40,-40,-50,-50,-40,-40,-30,
                -30,-40,-40,-50,-50,-40,-40,-30
            };
        }
        //Evaluationsfunktion zum berechnen der Punkte eines Spielers.
        //Wird durch den Suchalgorithmus zum berechnen des besten Zuges aufgerufen.
        public int GetValue(Game game,int player)
        {
           int temp =  game.CountValuesOf(player) - game.CountValuesOf(1 - player);
           return temp;
        }
        private int CountValuesOf(int player)
        {
            int value = 0;
            for (int row = 0; row < 8; row++)
            {
                for (int column = 0; column < 8; column++)
                {
                    if (player == 0)
                    {
                        switch (GetUnit(row, column))
                        {
                            case Game.UNIT.BBishop:
                                value += BBishopTable[(row * 8) + column];
                                value += Bishop;
                                break;
                            case Game.UNIT.BKing:
                                value += BKingTable[(row * 8) + column];
                                value += King;
                                break;
                            case Game.UNIT.BKnight:
                                value += BKnightTable[(row * 8) + column];
                                value += Knight;
                                break;
                            case Game.UNIT.BPawn:
                                value += BPawnTable[(row * 8) + column];
                                value += Pawn;
                                break;
                            case Game.UNIT.BQueen:
                                value += BQueenTable[(row * 8) + column];
                                value += Queen;
                                break;
                            case Game.UNIT.BRook:
                                value += BRookTable[(row * 8) + column];
                                value += Rook;
                                break;
                            default:
                                break;
                        }
                    }
                    else if (player == 1)
                    {
                        switch (GetUnit(row, column))
                        {
                            case Game.UNIT.WBishop:
                                value += WBishopTable[(row * 8) + column];
                                value += Bishop;
                                break;
                            case Game.UNIT.WKing:
                                value += WKingTable[(row * 8) + column];
                                value += King;
                                break;
                            case Game.UNIT.WKnight:
                                value += WKnightTable[(row * 8) + column];
                                value += Knight;
                                break;
                            case Game.UNIT.WPawn:
                                value += WPawnTable[(row * 8) + column];
                                value += Pawn;
                                break;
                            case Game.UNIT.WQueen:
                                value += WQueenTable[(row * 8) + column];
                                value += Queen;
                                break;
                            case Game.UNIT.WRook:
                                value += WRookTable[(row * 8) + column];
                                value += Rook;
                                break;
                            default:
                                break;;
                        }
                    }
                }
            }
            return value;
        }
        //Die Berechnungen (row + 2) * 10 + (column + 1) ist nötig, um aus der Row-Column-Darstellung 
        //des UI in den Index für das Board in der internen Darstellung zu erhalten.
        private Boolean PawnAt(int row, int column)
        {
            int piece = Board[((row + 2) * 10) + (column + 1)];
            return piece == 1 || piece == 2 ? true : false;
        }
        private Boolean KnightAt(int row, int column)
        {
            int piece = Board[((row + 2) * 10) + (column + 1)];
            return piece == 22 || piece == 12 ? true : false;
        }
        private Boolean BishopAt(int row, int column)
        {
            int piece = Board[((row + 2) * 10) + (column + 1)];
            return piece == 23 || piece == 13 ? true : false;
        }
        private Boolean RookAt(int row, int column)
        {
            int piece = Board[((row + 2) * 10) + (column + 1)];
            return piece == 21 || piece == 11 ? true : false;
        }
        private Boolean QueenAt(int row, int column)
        {
            int piece = Board[((row + 2) * 10) + (column + 1)];
            return piece == 24 || piece == 14 ? true : false;
        }
        private Boolean KingAt(int row, int column)
        {
            int piece = Board[((row + 2) * 10) + (column + 1)];
            return piece == 20 || piece == 10 ? true : false;
        }
        public Boolean BlackAt(int row, int column)
        {
            int piece = Board[((row + 2) * 10) + (column + 1)];
            return piece >= 20 || piece == 2 ? true : false;
        }
        private Boolean BlackAt(int index)
        {
            int piece = Board[index];
            return piece >= 20 || piece == 2 ? true : false;
        }
        public Boolean WhiteAt(int row, int column)
        {
            int piece = Board[((row + 2) * 10) + (column + 1)];
            return piece >= 10 && piece < 20 || piece == 1 ? true : false;
        }
        private Boolean WhiteAt(int index)
        {
            int piece = Board[index];
            return piece >= 10 && piece < 20 || piece == 1 ? true : false;
        }
        private Boolean PieceAt(int row, int column)
        {
            int piece = Board[((row + 2) * 10) + (column + 1)];
            return piece > 0 ? true : false;
        }
        //Prüft ob König im Schach steht.
        //Es wird vom König sternförmig nach außen geprüft. Dadurch werden nur die wirklich nötigen Felder überprüft und nicht alle 64.
        //Dies resultiert aber leider in etwas unsauberem und langen Code.
        public Boolean IsKingAttacked(int player)
        {
            int currentPosition;
            int currentRow;
            int currentColumn;
            int temp;
            
            //Index des Königs
            if (player == 0)
                currentPosition = Array.IndexOf(Board, 20);
            else
                currentPosition = Array.IndexOf(Board, 10);

            currentRow = (currentPosition / 10) - 2;
            currentColumn = (currentPosition % 10) - 1;
       
            temp = currentPosition;
            while (true)
            { counter++;
                temp += 10; //Felder vertikal abwärts
                if (Board[temp] != -1 && Board[temp] > 0) 
                {
                    //Wenn die Figur auf "temp" den König bedroht
                    if (IsAttacking(player, temp, currentRow, currentColumn))
                        return true;
                    else //Wenn die Figur auf "temp" nicht gefährlich für den König ist.
                        break;
                }
                else if (Board[temp] == -1) //Wenn Boardende erreicht
                    break;
               
            }
            temp = currentPosition;
            while (true)
            {  counter++;
                temp -= 10;
                if (Board[temp] != -1 && Board[temp] > 0)
                {
                    if (IsAttacking(player, temp, currentRow, currentColumn))
                        return true;
                    else
                        break;
                }
                else if (Board[temp] == -1)
                    break;
              
            }
            temp = currentPosition;
            while (true)
            { counter++;
                temp += 1;
                if (Board[temp] != -1 && Board[temp] > 0)
                {
                    if (IsAttacking(player, temp, currentRow, currentColumn))
                        return true;
                    else
                        break;
                }
                else if (Board[temp] == -1)
                    break;
               
            }
            temp = currentPosition;
            while (true)
            {counter++;
                temp -= 1;
                if (Board[temp] != -1 && Board[temp] > 0)
                {
                    if (IsAttacking(player, temp, currentRow, currentColumn))
                        return true;
                    else
                        break;
                }
                else if (Board[temp] == -1)
                    break;
                
            }

            temp = currentPosition;
            while (true)
            {counter++;
                temp += 11;
                if (Board[temp] != -1 && Board[temp] > 0)
                {
                    if (IsAttacking(player, temp, currentRow, currentColumn))
                        return true;
                    else
                        break;
                }
                else if (Board[temp] == -1)
                    break;
                
            }
            temp = currentPosition;
            while (true)
            { counter++;
                temp -= 11;
                if (Board[temp] != -1 && Board[temp] > 0)
                {
                    if (IsAttacking(player, temp, currentRow, currentColumn))
                        return true;
                    else
                        break;
                }
                else if (Board[temp] == -1)
                    break;
               
            }

            temp = currentPosition;
            while (true)
            {counter++;
                temp += 9;
                if (Board[temp] != -1 && Board[temp] > 0)
                {
                    if (IsAttacking(player, temp, currentRow, currentColumn))
                        return true;
                    else
                        break;
                }
                else if (Board[temp] == -1)
                    break;
                
            }
            temp = currentPosition;
            while (true)
            { counter++;
                temp -= 9;
                if (Board[temp] != -1 && Board[temp] > 0)
                {
                    if (IsAttacking(player, temp, currentRow, currentColumn))
                        return true;
                    else
                        break;
                }
                else if (Board[temp] == -1)
                    break;
               
            }
            //Folgende acht Prüfungen sind für den Springer
            temp = currentPosition;
            temp += 21;
            counter++;
            if (Board[temp] != -1 && Board[temp] > 0)
            {
                if (IsAttacking(player, temp, currentRow, currentColumn))
                    return true;
              
            }
            temp = currentPosition;
            temp -= 21;
            counter++;
            if (Board[temp] != -1 && Board[temp] > 0)
            {
                if (IsAttacking(player, temp, currentRow, currentColumn))
                    return true;

            }
            temp = currentPosition;
            temp += 19;
            counter++;
            if (Board[temp] != -1 && Board[temp] > 0)
            {
                if (IsAttacking(player, temp, currentRow, currentColumn))
                    return true;

            }
            temp = currentPosition;
            temp -= 19;
            counter++;
            if (Board[temp] != -1 && Board[temp] > 0)
            {
                if (IsAttacking(player, temp, currentRow, currentColumn))
                    return true;

            }
            temp = currentPosition;
            temp += 12;
            counter++;
            if (Board[temp] != -1 && Board[temp] > 0)
            {
                if (IsAttacking(player, temp, currentRow, currentColumn))
                    return true;

            }
            temp = currentPosition;
            temp -= 12;
            counter++;
            if (Board[temp] != -1 && Board[temp] > 0)
            {
                if (IsAttacking(player, temp, currentRow, currentColumn))
                    return true;

            }
            temp = currentPosition;
            temp += 8;
            counter++;
            if (Board[temp] != -1 && Board[temp] > 0)
            {
                if (IsAttacking(player, temp, currentRow, currentColumn))
                    return true;

            }
            temp = currentPosition;
            temp -= 8;
            counter++;
            if (Board[temp] != -1 && Board[temp] > 0)
            {
                if (IsAttacking(player, temp, currentRow, currentColumn))
                    return true;

            }
            

            return false;
        }
        private Boolean IsAttacking(int player, int temp, int currentRow, int currentColumn)
        {
            if (WhiteAt(temp) && player == 1)
            {
                return false;                
            }
            else if (BlackAt(temp) && player == 0)
            {
                return false;
            }
            else
            {
                int targetRow = (temp / 10) - 2;
                int targetColumn = (temp % 10) - 1;
                return gameRules.IsLegal(new ChessMove(1 - player, targetRow, targetColumn, currentRow, currentColumn), this);
            }
        }
        //Erstellt eine Kopie des Game Objektes und führt einen Zug aus.
        //So kann der Suchalgorithmus "in die Zukunft schauen."
        //Wir die Kopie nicht mehr benötigt, wird sie verworfen und
        //fällt dem Garbage-Collector zum Opfer.
        public Game CopyAndMove(ChessMove move)
        {
            Game copy = new Game(this);
            copy.MakeMove(move);
            return copy;
        }
        public void MakeMove(ChessMove move)
        {
            CheckGameOver(move);
            if (!_gameOver)
                SetUnit(move);
        }
        private void SetUnit(ChessMove move)
        {
            int piece = Board[((move.CurrentRow + 2) * 10) + (move.CurrentColumn + 1)];
            Board[((move.TargetRow + 2) * 10) + (move.TargetColumn + 1)] = piece;
            Board[((move.CurrentRow + 2) * 10) + (move.CurrentColumn + 1)] = 0;

            if(piece == 1 || piece == 2)
                CheckPromotion(move, piece);

            SetCastlingRights(move, piece);                     
        }
        //Wenn ein Bauer bis in die erste Reihe des Gegners bewegt wird, wird er befördert
        //und wird zu einer Dame.
        private void CheckPromotion(ChessMove move, int piece)
        {
            int index = (move.TargetRow + 2) * 10 + (move.TargetColumn + 1);
            if (piece == 1)
            {
                if (index >= 21 && index <= 28)
                    PromotePawn(move, piece);
            }
            else if (piece == 2)
            {
                if (index >= 91 && index <= 98)
                    PromotePawn(move, piece);
            }
        }
        private void PromotePawn(ChessMove move, int piece)
        {
            if (piece == 1)
                Board[((move.TargetRow + 2) * 10) + (move.TargetColumn + 1)] = 14;
            else
                Board[((move.TargetRow + 2) * 10) + (move.TargetColumn + 1)] = 24;
        }
        //Setzt, wenn z.B. der Turm bewegt wurde ein bool, dass mit diesem keine Rochade mehr möglich ist.
        private void SetCastlingRights(ChessMove move, int piece)
        {
            if (piece == 10)
            {
                if (move.TargetColumn == 1 && move.TargetRow == 7 && castlingLeftforWhitePossible)
                {
                    Board[93] = Board[91];
                    Board[91] = 0;
                }
                else if (move.TargetColumn == 6 && move.TargetRow == 7 && castlingRightforWhitePossible)
                {
                    Board[96] = Board[98];
                    Board[98] = 0;
                }
                castlingRightforWhitePossible = false;
                castlingRightforWhitePossible = false;
            }

            if (piece == 20)
            {
                if (move.TargetColumn == 1 && move.TargetRow == 0 && castlingLeftforBlackPossible)
                {
                    Board[23] = Board[21];
                    Board[21] = 0;
                }
                else if (move.TargetColumn == 6 && move.TargetRow == 0 && castlingRightforBlackPossible)
                {
                    Board[26] = Board[28];
                    Board[28] = 0;
                }
                castlingRightforBlackPossible = false;
                castlingRightforBlackPossible = false;
            }

            if (piece == 11)
            {
                if (move.CurrentColumn == 7)
                {
                    castlingRightforWhitePossible = false;
                }
                else if (move.CurrentColumn == 0)
                {
                    castlingLeftforWhitePossible = false;
                }
            }

            if (piece == 21)
            {
                if (move.CurrentColumn == 7)
                {
                    castlingRightforBlackPossible = false;
                }
                else if (move.CurrentColumn == 0)
                {
                    castlingLeftforBlackPossible = false;
                }
            }
        }
        
        private void CheckGameOver(ChessMove move)
        {
           if (GetUnit(move.TargetRow, move.TargetColumn) == UNIT.BKing || GetUnit(move.TargetRow, move.TargetColumn) == UNIT.WKing)
               _gameOver = true;
           if(move.Check)
               _gameOver = true;
        }               
        public UNIT GetUnit(int row, int column)
        {
                if (PawnAt(row, column))
                    return (BlackAt(row, column) ? UNIT.BPawn : UNIT.WPawn);
                if (KnightAt(row, column))
                    return (BlackAt(row, column) ? UNIT.BKnight : UNIT.WKnight);
                if (BishopAt(row, column))
                    return (BlackAt(row, column) ? UNIT.BBishop : UNIT.WBishop);
                if (RookAt(row, column))
                    return (BlackAt(row, column) ? UNIT.BRook : UNIT.WRook);
                if (QueenAt(row, column))
                    return (BlackAt(row, column) ? UNIT.BQueen : UNIT.WQueen);
                if (KingAt(row, column))
                    return (BlackAt(row, column) ? UNIT.BKing : UNIT.WKing);
            return UNIT.Free;
        }
        // Einfaches Aufzählen aller gültigen Züge von oben links bis unten rechts
        public IEnumerable<ChessMove> MovesFor(int playerId)
        {           
            int moveCount = 0;
            for(int row = 0; row < 8; row++)
            {
                for(int column = 0; column < 8; column++)
                {
                    if(Board[((row + 2) * 10) + (column + 1)] > 0 )
                    {
                            
                        for (int i = 0; i < 8; ++i)
                        {
                            for (int j = 0; j < 8; ++j)
                            {
                                if (gameRules.IsLegal(new ChessMove(playerId,row,column, i, j), this))
                                {
                                    if (!CopyAndMove(new ChessMove(playerId, row, column, i, j)).IsKingAttacked(playerId))
                                    {
                                        ++moveCount;
                                        yield return new ChessMove(playerId, row, column, i, j);
                                    }
                                }
                            }
                        }
                            
                    }
                    }

                }
                //Wenn kein gültiger Zug möglich ist, wird eine "Schachmatt-Move" ausgeführt. 
                if (moveCount == 0)
                {
                    yield return new ChessMove(playerId, true);
                }
                
            }
        public bool isCastlingLeftforWhitePossible()
        {
            return castlingLeftforWhitePossible;
        }

        public bool isCastlingRightforWhitePossible()
        {
            return castlingRightforWhitePossible;
        }

        public bool isCastlingLeftforBlackPossible()
        {
            return castlingLeftforBlackPossible;
        }

        public bool isCastlingRightforBlackPossible()
        {
            return castlingRightforBlackPossible;
        }
        public bool GameOver
        {
            get
            {
                return _gameOver;
            }
            set
            {
                _gameOver = GameOver;
            }
        }            
    }
}
